/**
 * \class CubeServices
 * \brief This is a user interface for services.
 * \version 0.3.2
 *
 * \author Woo-Hyun Kim (woorung@nhncorp.com, woorung@gmail.com)
 * \author http://blog.naver.com/wisereign .
 *
 * \date 2008/7/6
 */
#include "CubeServices.h"

CubeServices::CubeServices()
{
	this->host = "";
	this->port = -1;
}

CubeServices::CubeServices(char *host, int port)
{
	this->host = host;
	this->port = port;
}

CubeServices::~CubeServices()
{
}

int CubeServices::connect(char *host, int port)
{
	this->host = host;
	this->port = port;
}

// keyval-based invoke
int CubeServices::invoke(char *servicename, map<string,string> &in, map<string,string> &out)
{
	if(host==""||port<0) {
		cerr << "ERROR : there is no discovery address and port" << endl;
		return -1;
	}

	CServiceInfo service_info;
	service_info.setName(servicename);

	vector<CServiceInfo> services;
	
	CDiscoveryProxy *discovery = new CDiscoveryProxy((char *)host.c_str(), port);
	services = discovery->discover(&service_info);
	delete discovery;


	// sort in service's load order
	//---------------------------------------------------------------------------------------
	vector< pair<float, CServiceInfo *> > load_order;
	for(int i=0;i<services.size();i++) {
		CServiceInfo *found = &(services[i]);

		load_order.push_back(vector< pair<float,CServiceInfo *> >::value_type(found->getLoad(), found));
	}

	sort(load_order.begin(),load_order.end());

#ifdef DEBUG
	for(int i=0;i<load_order.size();i++) {
		cout << load_order[i].second->getIP() << ":" << load_order[i].second->getPort() << "\t" << load_order[i].second->getLoad() << endl;
	}
#endif
	//---------------------------------------------------------------------------------------

	int best = 0;

	// remote invocation
	CServiceProxy proxy;
	proxy.connect(load_order[best].second->getIP(), load_order[best].second->getPort());

	return proxy.invoke(servicename, in, out);
}
